#!/usr/bin/env python
# encoding: utf-8
"""
movingAverage.py

Created by Dmitry Tsybin on 2011-03-09.
Copyright (c) 2011. All rights reserved.
"""

import sys
import os
import unittest
from constants import *

class MovingAverage:
	'''Класс для использования методов скользящего среднего.
	В данный момент реализован алгоритм сравнения значения WMA с порогом'''
	
	def __init__(self):
		self.counter = 0
		
		self.simpleSum = 0
		self.weightSum = 0
		
		self.shortSample = []
		self.longSample = []
		
		self.shortPop = 0
		self.longPop = 0
		
		self.wmaThresholdDiscord = 0.01
		self.wmaThresholdCrash = 0.05
	
	def sma(self, nowValue):
		'''Простая скользящая средняя.'''
		self.counter += 1
		self.simpleSum += nowValue
		return self.simpleSum / self.counter 
		
	def wma(self, nowValue):
		'''Взвешенная скользящая средняя'''
		numerator = 0
		denominator = 0
		self.counter += 1
		
		denominator = ((1 + self.counter) / 2) * self.counter
		self.weightSum = self.weightSum + nowValue * self.counter
		return self.weightSum / denominator
		
	def discord(self, nowValue, shortMA = 10, longMA = 100):
		'''функция возвращает STATUS'''
		if len(self.shortSample) < shortMA:
			if len(self.longSample) != len(self.shortSample):
				raise
			self.shortSample.append(nowValue)
			self.longSample.append(nowValue)
			status = STATUS.ok
		elif len(self.longSample) < longMA:
			self.shortPop = self.shortSample.pop(0)
			self.shortSample.append(nowValue)
			self.longSample.append(nowValue)
			status = STATUS.ok
		else:
			self.shortPop = self.shortSample.pop(0)
			self.shortSample.append(nowValue)
			self.longPop = self.longSample.pop(0)
			self.longSample.append(nowValue)
			
			weightAverage = self.wma(nowValue)

			
			if weightAverage < self.wmaThresholdDiscord:
				status = STATUS.ok

			elif weightAverage < self.wmaThresholdCrash:
				status = STATUS.discord

			else:
				status = STATUS.crash
				
		self.counter += 1
		return status	
			

class MovingAverageTest(unittest.TestCase):
	knownValues1 = [0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09]
	knownValues2 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
	knownValues3 = []

	def testSMA1(self):
		testUnit = MovingAverage()
		result = 0
		for nowVal in self.knownValues1:
			result = testUnit.sma(nowVal)
		self.assertAlmostEqual(0.05, result)
		
	def testSMA2(self):
		testUnit = MovingAverage()
		result = 0
		for nowVal in self.knownValues2:
			result = testUnit.sma(nowVal)
		self.assertEqual(5, result)
		
	def testSMA3(self):
		testUnit = MovingAverage()
		result = 0
		for nowVal in self.knownValues3:
			result = testUnit.sma(nowVal)
		self.assertEqual(0, result)
		
	def testWMA1(self):
		testUnit = MovingAverage()
		result = 0
		for nowVal in self.knownValues1:
			result = testUnit.wma(nowVal)
		self.assertAlmostEqual(2.85/45, result)

	def testWMA2(self):
		testUnit = MovingAverage()
		result = 0
		for nowVal in self.knownValues2:
			result = testUnit.wma(nowVal)
		self.assertAlmostEqual(285/45, result)
		
	def testWMA3(self):
		testUnit = MovingAverage()
		result = 0
		for nowVal in self.knownValues3:
			result = testUnit.wma(nowVal)
		self.assertEqual(0, result)
	
	def testDiscord1(self):
		testUnit = MovingAverage()
		i = 0
		while i < 100:
			res = testUnit.discord(i)
			self.assertEqual(STATUS.ok, res)
			i += 1
		self.assertEqual(list(range(90,100)),testUnit.shortSample)
		self.assertEqual(list(range(100)) ,testUnit.longSample)
		
	def testDiscord2(self):
		testUnit = MovingAverage()
		i = 0
		while i < 110:
			result = testUnit.discord(i/1000)
			i += 1
		self.assertEqual(STATUS.discord, result)
			


if __name__ == '__main__':
	unittest.main()	